﻿/*
 * Author: Alexander Sjösten
 * Thomas Mattsson wrote GetSessionStrings and GetIndexStartingFromEndOfList
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using Final_Project.SessionData;

namespace Final_Project.CustomerData
{
    [Serializable()]
    /// <summary>
    /// This class represents a Customer.
    /// It manages its own list of TreatmentSessions.
    /// </summary>
    public class Customer : ISerializable
    {
        // Local variables
        private int id;
        private string firstName;
        private string lastName;
        private string phoneNbr;
        private string email;
        private List<TreatmentSession> sessions;


        /// <summary>
        /// Constructor for Customer taking 0 parameters,
        /// will chain call next constructor
        /// </summary>
        public Customer()
            : this(0)
        { }


        /// <summary>
        /// Constructor for Customer taking 1 parameter,
        /// will chain call next constructor
        /// </summary>
        /// <param name="id">The id of the customer</param>
        public Customer(int id)
            : this(id, string.Empty)
        { }


        /// <summary>
        /// Constructor for Customer taking 2 parameters,
        /// will chain call next constructor
        /// </summary>
        /// <param name="id">The id of the customer</param>
        /// <param name="firstName">The first name of the customer</param>
        public Customer(int id, string firstName)
            : this(id, firstName, string.Empty)
        { }

        
        /// <summary>
        /// Constructor for Customer taking 3 parameters,
        /// will chain call next constructor
        /// </summary>
        /// <param name="id">The id of the customer</param>
        /// <param name="firstName">The first name of the customer</param>
        /// <param name="lastName">The last name of the customer</param>
        public Customer(int id, string firstName, string lastName)
            : this(id, firstName, lastName, string.Empty)
        { }


        /// <summary>
        /// Constructor for Customer taking 4 parameters,
        /// will chain call next constructor
        /// </summary>
        /// <param name="id">The id of the customer</param>
        /// <param name="firstName">The first name of the customer</param>
        /// <param name="lastName">The last name of the customer</param>
        /// <param name="phoneNbr">The phone number of the customer</param>
        public Customer(int id, string firstName, string lastName, string phoneNbr)
            : this(id, firstName, lastName, phoneNbr, string.Empty)
        { }


        /// <summary>
        /// Constructor for Customer taking 5 parameters,
        /// will chain call next constructor
        /// </summary>
        /// <param name="id">The id of the customer</param>
        /// <param name="firstName">The first name of the customer</param>
        /// <param name="lastName">The last name of the customer</param>
        /// <param name="phoneNbr">The phone number of the customer</param>
        /// <param name="email">The email address of the customer</param>
        public Customer(int id, string firstName, string lastName, string phoneNbr, string email)
            : this(id, firstName, lastName, phoneNbr, string.Empty, new List<TreatmentSession>())
        { }

        
        /// <summary>
        /// Constructor taking 6 parameters
        /// </summary>
        /// <param name="id">The id of the customer</param>
        /// <param name="firstName">The first name of the customer</param>
        /// <param name="lastName">The last name of the customer</param>
        /// <param name="phoneNbr">The phone number of the customer</param>
        /// <param name="email">The email address of the customer</param>
        /// <param name="sessions">The list of sessions for the customer</param>
        public Customer(int id, string firstName, string lastName, string phoneNbr, string email, List<TreatmentSession> sessions)
        {
            this.id = id;
            this.firstName = firstName;
            this.lastName = lastName;
            this.phoneNbr = phoneNbr;
            this.email = email;
            this.sessions = sessions;
        }


        /// <summary>
        /// Copy constructor so we don't mess around too much with references...
        /// </summary>
        /// <param name="customer">The customer to copy from</param>
        public Customer(Customer customer)
        {
            id = customer.ID;
            firstName = customer.FirstName;
            lastName = customer.LastName;
            phoneNbr = customer.Phone;
            email = customer.Email;
            sessions = new List<TreatmentSession>(customer.SessionsList);
        }


        /// <summary>
        /// Copy-constructor that takes an InvoiceCustomer
        /// and returns a new reference to a Customer object.
        /// </summary>
        /// <param name="invCustomer">The InvoiceCustomer to copy.</param>
        public Customer(InvoiceCustomer invCustomer)
            : this(invCustomer.ID, invCustomer.FirstName, invCustomer.LastName,
                invCustomer.Phone, invCustomer.Email, invCustomer.SessionsList)
        { }

        /// <summary>
        /// Deserialization constructor
        /// </summary>
        /// <param name="info">The information to the object from the deserialization</param>
        /// <param name="ctxt">The streaming context</param>
        public Customer(SerializationInfo info, StreamingContext ctxt)
        {
            id = (int)info.GetValue("IDInfo", typeof(int));
            firstName = (String)info.GetValue("FirstNameInfo", typeof(string));
            lastName = (String)info.GetValue("LastNameInfo", typeof(string));
            phoneNbr = (String)info.GetValue("PhoneInfo", typeof(string));
            email = (String)info.GetValue("EmailInfo", typeof(string));
            sessions = (List<TreatmentSession>)info.GetValue("SessionsInfo", typeof(List<TreatmentSession>));
        }


        /// <summary>
        /// Method to add a TreatmentSession to the customer
        /// </summary>
        /// <param name="session">The TreatmentSession to be added</param>
        public void AddSession(TreatmentSession session)
        {
            sessions.Add(session);
        }

        
        /// <summary>
        /// Method to remove a specific TreatmentSession from the customer
        /// </summary>
        /// <param name="session">TreatmentSession to be removed</param>
        public void RemoveSession(TreatmentSession session)
        {
            sessions.Remove(session);
        }

        
        /// <summary>
        /// Method to remove a specific TreatmentSession from the customer
        /// using the index of where it is in the list
        /// </summary>
        /// <param name="index">The index of the TreatmentSession to be removed</param>
        public void RemoveSession(int index)
        {
            if (CheckIndex(index))
            {
                int newIndex = GetIndexStartingFromEndOfList(index);
                sessions.RemoveAt(newIndex);
            }
        }


        /// <summary>
        /// This method creates an array of strings from the (reversed) list
        /// of sessions that this customer has.
        /// This is done because date ordering is "most recent first".
        /// </summary>
        /// <returns>Array of session strings.</returns>
        public string[] GetSessionsStrings()
        {
            int max = sessions.Count;
            string[] reversedStrings = new string[max];

            for (int i=0, j=(max-1); i<max; i++,j--)
            {
                reversedStrings[i] = sessions.ElementAt(j).ToString();
            }
            return reversedStrings;
        }


        /// <summary>
        /// This method calculates the correct index into the sessions list.
        /// </summary>
        /// <param name="index">The index to be used from end of list</param>
        /// <returns>The correct list index</returns>
        private int GetIndexStartingFromEndOfList(int index)
        {
            if (CheckIndex(index))
            {
                int indexFromEndOfList = (sessions.Count - 1) - index;
                return indexFromEndOfList;
            }
            else
            {
                return -1;
            }
        }


        /// <summary>
        /// Returns a specific TreatmentSession from the list.
        /// Calculates the correct position in the list from the 
        /// given index.
        /// </summary>
        /// <param name="index">The index to search for.</param>
        /// <returns>The sought TreatmentSession if found, otherwise null.</returns>
        public TreatmentSession GetTreatmentSession(int index)
        {
            if (CheckIndex(index))
            {
                int result = GetIndexStartingFromEndOfList(index);
                return sessions.ElementAt(result);
            }
            return null;
        }


        /// <summary>
        /// Checks that index is within sessions list's bounds.
        /// </summary>
        /// <param name="index">The index to check.</param>
        /// <returns>True if index is within bounds, False otherwise.</returns>
        private bool CheckIndex(int index)
        {
            return (index >= 0 && index < sessions.Count);
        }


        /// <summary>
        /// ToString method to show the information about the customer
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return string.Format("{0, -5} {1, -28} {2, -12} {3, -30} {4, 4}", ID, FullName, Phone, Email, sessions.Count);
        }

        
        /// <summary>
        /// Property for getting and setting the id of the customer
        /// </summary>
        public int ID
        {
            get { return id; }
            set
            {
                if (value > 0)
                    id = value;
            }
        }


        /// <summary>
        /// Property for getting and setting the firstName-variable
        /// </summary>
        public string FirstName
        {
            get { return firstName; }
            set
            {
                if (!string.IsNullOrEmpty(value))
                    firstName = value;
            }
        }


        /// <summary>
        /// Property for getting and setting the lastName-variable
        /// </summary>
        public string LastName
        {
            get { return lastName; }
            set
            {
                if (!string.IsNullOrEmpty(value))
                    lastName = value;
            }
        }


        /// <summary>
        /// Property for getting the name of the customer
        /// </summary>
        public string FullName
        {
            get { return FirstName + " " + LastName; }
        }

        
        /// <summary>
        /// Property related to the phoneNbr variable.
        /// </summary>
        public string Phone
        {
            get { return phoneNbr; }
            set
            {
                if (!string.IsNullOrEmpty(value))
                {
                    phoneNbr = value;
                }
            }
        }


        /// <summary>
        /// Property related to the email variable.
        /// </summary>
        public string Email
        {
            get { return email; }
            set
            {
                if (!string.IsNullOrEmpty(value))
                    email = value;
            }
        }

        /// <summary>
        /// Property related to the sessions variable.
        /// </summary>
        public List<TreatmentSession> SessionsList
        {
            get { return sessions; }
            set
            {
                if (value != null)
                    sessions = value;
            }
        }

        /// <summary>
        /// Method for serialization, must be added since it's
        /// part of the ISerializable interface
        /// </summary>
        /// <param name="info">The serialization info</param>
        /// <param name="ctxt">The streaming context</param>
        public virtual void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            info.AddValue("IDInfo", ID);
            info.AddValue("FirstNameInfo", FirstName);
            info.AddValue("LastNameInfo", LastName);
            info.AddValue("PhoneInfo", Phone);
            info.AddValue("EmailInfo", Email);
            info.AddValue("SessionsInfo", SessionsList);
        }
    }
}